﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace VideoClipNameHelper
{
    public class ConfigPaths
    {
        public string ReportsDir { get; set; }
        public string[] SourceDirs { get; set; }
        public string ByArtistDir { get; set; }
        public string ByAlbumDir { get; set; }
        public string ByTitleDir { get; set; }
        public string ByYearDir { get; set; }
        public string ByNewerDir { get; set; }
        public string ByLikedDir { get; set; }
        public string SpecialListsDir { get; set; }
        public string[] SpecialListsPathnames { get; set; }
    }
            //

    public class ConfigData
    {
        /// <summary>
        /// w katalogu programu
        /// </summary>
        public static readonly string ConfigFileName = "VideoClipsConfig.txt";
        public enum KeyName { Unknown,
            /// <summary>
            /// Absolute Path, ConfigFileName
            /// </summary>
            ConfigFileFullPath,
            /// <summary>
            /// Absolute Path, tam katalogi źródłowe ze clipami
            /// </summary>
            SourceRoot,

            /// <summary>
            /// Delimited list of source directories
            /// </summary>
            ListOfSources,

            /// <summary>
            /// Directory Name, znajduje się tam gdzie EXE
            /// katalog raportów
            /// </summary>
            DirectoryContainsReports,

            /// <summary>
            /// Directory Name, znajduje się tam gdzie EXE
            /// w pliku lista nazw plików, bez ścieżek,
            /// do odczytanych nazw plików dodawana jest ścieżka katalogów
            /// </summary>
            DirectoryContainsSpecialListsFiles,
            //----------------------------
            /// <summary>
            /// Absolute Path, tam tworzone są katalogi wynikowe
            /// </summary>
            DestinationRoot,

            /// <summary>
            /// Directory Name, inside DestinationRoot
            /// </summary>
            ByArtistDirectory,

            /// <summary>
            /// Directory Name, inside DestinationRoot
            /// </summary>
            ByAlbumDirectory,

            /// <summary>
            /// Directory Name, inside DestinationRoot
            /// </summary>
            ByTitleDirectory,

            /// <summary>
            /// Directory Name, inside DestinationRoot
            /// </summary>
            ByYearDirectory,

            /// <summary>
            /// Directory Name, inside DestinationRoot
            /// </summary>
            /// 
            ByNewDirectory,
            /// <summary>
            /// Directory Name, inside DestinationRoot
            /// </summary>
            ByLikedDirectory,
            /// <summary>
            /// Directory Name, inside DestinationRoot
            /// </summary>
            BySpecialListsDirectory
        }
        public static readonly KeyName[] AlwaysDefined = { KeyName.SourceRoot, KeyName.DestinationRoot, KeyName.DirectoryContainsReports, KeyName.ListOfSources, KeyName.ByArtistDirectory, KeyName.ByAlbumDirectory, KeyName.ByTitleDirectory, KeyName.BySpecialListsDirectory, KeyName.ByLikedDirectory, KeyName.DirectoryContainsSpecialListsFiles };
        private static Dictionary<KeyName, string> configDictionary = new Dictionary<KeyName, string>();

        public static Dictionary<string, string> ReadConfig(ConfigPaths cp)
        {
            Dictionary<string, string> allKeys = new Dictionary<string, string>();
            //
            if (!System.IO.File.Exists(ConfigFileName))
            {
                throw new InvalidOperationException(string.Format("File not found: [{0}]", ConfigFileName));
            }
            //
            configDictionary.Add(KeyName.ConfigFileFullPath, System.IO.Path.GetFullPath(ConfigFileName));
            //
            string[] ll = System.IO.File.ReadAllLines(ConfigFileName, Encoding.UTF8);
            foreach(string l in ll)
            {
                if ("" == l.Trim() || l.TrimStart().StartsWith("#") || l.TrimStart().StartsWith("//"))
                {
                    continue;
                }
                string[] pp = l.Split(new[] { '=' }, 2);
                pp[0] = pp[0].Trim().ToUpper();
                pp[1] = pp[1].Trim();
                //
                allKeys[pp[0]] = pp[1];
                //
                KeyName result;
                if(!Enum.TryParse<KeyName>(pp[0], true, out result))
                {
                    continue;
                }
                //
                if(configDictionary.ContainsKey(result))
                {
                    throw new FormatException(string.Format("Config File: [{0}] - Key [{1}] already added",ConfigFileName, result));
                }

                configDictionary.Add(result, pp[1]);
                //
            }

            string [] nc = (from x in AlwaysDefined where !configDictionary.ContainsKey(x) select x.ToString()).ToArray();
            if (nc.Count() > 0)
            {
                throw new FormatException(string.Format("Config File: [{0}] - lack of keys [{1}]", ConfigFileName, string.Join(",", nc)));
            }
            //
            //
            cp.ReportsDir = ConfigData.GetFullPath(ConfigData.KeyName.DirectoryContainsReports);
            cp.SourceDirs = ConfigData.GetListOfSourceDirectories();
            cp.ByArtistDir = ConfigData.GetFullPath(ConfigData.KeyName.ByArtistDirectory);
            cp.ByAlbumDir = ConfigData.GetFullPath(ConfigData.KeyName.ByAlbumDirectory);
            cp.ByTitleDir = ConfigData.GetFullPath(ConfigData.KeyName.ByTitleDirectory);
            cp.ByYearDir = ConfigData.GetFullPath(ConfigData.KeyName.ByYearDirectory);
            cp.ByNewerDir = ConfigData.GetFullPath(ConfigData.KeyName.ByNewDirectory);
            cp.ByLikedDir = ConfigData.GetFullPath(ConfigData.KeyName.ByLikedDirectory);
            cp.SpecialListsDir = ConfigData.GetFullPath(ConfigData.KeyName.BySpecialListsDirectory);
            cp.SpecialListsPathnames = ConfigData.GetSpecialFilesWithFullPath();
            //
            //
            return allKeys;
        }


        private static string createFullPath(string defaultDirectory, string dirName)
        {
            if("" == System.IO.Path.GetDirectoryName(dirName))
            {
                return System.IO.Path.Combine(defaultDirectory, dirName);
            }

            return dirName;
        }

        public static string GetFullPath(KeyName key)
        {
            //
            if(key == KeyName.SourceRoot)
            {
                return configDictionary[KeyName.SourceRoot];
            }
            //if(key == KeyName.ListOfSources)
            //{
            //    return System.IO.Path.Combine(Environment.CurrentDirectory, configDictionary[KeyName.ListOfSources]);
            //}
            if (key == KeyName.DirectoryContainsReports)
            {
                return createFullPath(configDictionary[KeyName.SourceRoot], configDictionary[KeyName.DirectoryContainsReports]);
                //return System.IO.Path.Combine(Environment.CurrentDirectory, configDictionary[KeyName.DirectoryContainsReports]);
            }
            if (key == KeyName.DirectoryContainsSpecialListsFiles)
            {
                return createFullPath(configDictionary[KeyName.SourceRoot], configDictionary[KeyName.DirectoryContainsSpecialListsFiles]);
                //return System.IO.Path.Combine(Environment.CurrentDirectory, configDictionary[KeyName.DirectoryContainsSpecialListsFiles]);

            }
            //
            //
            //
            if (key == KeyName.DestinationRoot)
            {
                return configDictionary[KeyName.DestinationRoot];
            }
            //
            if (!configDictionary.ContainsKey(key))
            {
                return "";
            }
            //
            string p = configDictionary[key];
            if ("" == p) return "";
            if("" != System.IO.Path.GetDirectoryName(p))
            {
                return p;
            }

            return System.IO.Path.Combine(configDictionary[KeyName.DestinationRoot], p);
        }
        //Microsoft.VisualBasic.FileIO
        //https://coding.abel.nu/2012/06/built-in-net-csv-parser/

        public static string[] GetListOfSourceDirectories()
        {
            string[] paths;
            string lineListOfPaths = configDictionary[KeyName.ListOfSources];
            //
            using (MemoryStream ms = new MemoryStream(1000))
            {
                byte[] lopbs = System.Text.Encoding.UTF8.GetBytes(lineListOfPaths);
                ms.Write(lopbs, 0, lopbs.Length);
                ms.Seek(0, SeekOrigin.Begin);
                //
                using (Microsoft.VisualBasic.FileIO.TextFieldParser parser = new Microsoft.VisualBasic.FileIO.TextFieldParser(ms))
                {
                    parser.CommentTokens = new string[] { "#" };
                    parser.SetDelimiters(new string[] { ";" });
                    parser.TrimWhiteSpace = true;
                    //parser.HasFieldsEnclosedInQuotes = true;
                    //
                    // Skip over header line.
                    //parser.ReadLine();
                    paths = parser.ReadFields();
                    //return fields;
                    /*
                                    while (!parser.EndOfData)
                                    {
                                        string[] fields = parser.ReadFields();
                                        yield return new Brand()
                                        {
                                            Name = fields[0],
                                            FactoryLocation = fields[1],
                                            EstablishedYear = int.Parse(fields[2]),
                                            Profit = double.Parse(fields[3], swedishCulture)
                                        };
                                    }
                    */
                }
            }
            //
            List<string> lf = new List<string>();
            for (int i = 0; i < paths.Count(); i++)
            {
                if ("" == paths[i]) continue;
                if ("" == System.IO.Path.GetDirectoryName(paths[i]))
                {
                    lf.Add(System.IO.Path.Combine(configDictionary[KeyName.SourceRoot], paths[i]));
                }
                else
                {
                    lf.Add(paths[i]);
                }
            }
            //
            return lf.ToArray();
        }
/*
        public static string[] __GetListOfSourceDirectories()
        {
            List<string> lf = new List<string>();
            string fileName = configDictionary[KeyName.ListOfSources];
            if(!System.IO.File.Exists(fileName))
            {
                throw new Exception(string.Format("File not found: [{0}], Directory:[{1}]", fileName, Environment.CurrentDirectory));
            }
            string [] ll = System.IO.File.ReadAllLines(configDictionary[KeyName.ListOfSources], Encoding.UTF8);
            for(int i=0; i<ll.Count(); i++)
            {
                ll[i] = ll[i].Trim();
                if("" == ll[i])continue;
                if(ll[i].StartsWith("//")|| ll[i].StartsWith("#"))continue;
                if("" == System.IO.Path.GetDirectoryName(ll[i]))
                {
                    ll[i] = System.IO.Path.Combine(configDictionary[KeyName.SourceRoot], ll[i]);
                }
                lf.Add(ll[i]);
            }
            return lf.ToArray();
        }
*/
        public static string[] GetSpecialFilesWithFullPath()
        {
            List<string> specialFilesPathnames = new List<string>();

            //string specialListsDirectory = System.IO.Path.Combine(Environment.CurrentDirectory, configDictionary[KeyName.DirectoryContainsSpecialListsFiles]);
            //string specialListsDirectory = System.IO.Path.Combine(Environment.CurrentDirectory, configDictionary[KeyName.DirectoryContainsSpecialListsFiles]);
            string specialListsDirectory = GetFullPath(KeyName.DirectoryContainsSpecialListsFiles);
            foreach (string fn in System.IO.Directory.GetFiles(specialListsDirectory, "*.txt", System.IO.SearchOption.TopDirectoryOnly))
            {
                specialFilesPathnames.Add(fn);
            }

            return specialFilesPathnames.ToArray();
        }

        private static string[] SplitParameter(string pp)
        {
            string[] ppp = pp.Split(new[] { ',' });
            for(int i=0;i<ppp.Length; i++)
            {
                ppp[i] = ppp[i].Trim();
            }
            return ppp;
        }

        public static KeyName GetSpecialDirectoryFromPath(string path)
        {
            string [] partsPath = path.Split(System.IO.Path.PathSeparator);
            if (partsPath.Count() > 1)
            {
                path = partsPath[partsPath.Count() - 1];
            }
            foreach(KeyValuePair<KeyName, string> kvp in configDictionary)
            {
                if(0==string.Compare(path, kvp.Value, true))
                {
                    return kvp.Key;
                }
            }
            return KeyName.Unknown;
        }

        public static bool ValueAsBool(string value)
        {
            value = value.Trim();
            //
            if (0 == string.Compare(value, "true", true)) return true;
            if (0 == string.Compare(value, "1", true)) return true;
            //
            return false;
        }
    }//class
}//namespace
